import {FuncExtInit} from "../FuncExt";
function FuncExtInitFunc() {
    FuncExtInit();
}
import {MapString} from "./sdf";

/**
 * 通过@装饰器设置的class的元数据
 */
export interface ClassMetaData {
    _fieldMetaDataMap_?: MapString<Object>;
}

/**
 * 元数据操作类
 */
export class Meta {
    /**
     * 装饰Array的成员类型
     * @param clas
     * @returns {function(Object, string): undefined}
     * @constructor
     */
    static arrayType<T>(clas: { new(): T ;}) {
        return (target: Object, propertyKey: string)=> {
            Meta.setData(target.constructor, "Meta.arrayType", propertyKey, clas);
        }
    }

    static getArrayType(clas: { new(): any ;}, field: string) {
        return Meta.getData(clas, "Meta.arrayType", field) as { new(): any ;};
    }

    /**
     * 获取class@装饰器设置的元数据
     * @param clas class名
     * @param metaKey 元数据键值
     * @param field class成员名
     * @returns {any} 未找到返回null
     */
    static getData(clas: ClassMetaData, metaKey: string, field: string) {
        if (!clas || !clas._fieldMetaDataMap_)
            return null;

        return clas._fieldMetaDataMap_[Meta.getKey(metaKey, field)];
    }

    /**
     * 设置class的元数据
     * @param classType
     * @param metaKey 元数据键值
     * @param field class成员名
     * @param data
     */
    static setData(classType: ClassMetaData, metaKey: string, field: string, data: any) {
        if (!classType._fieldMetaDataMap_)
            classType._fieldMetaDataMap_ = {};
        classType._fieldMetaDataMap_[Meta.getKey(metaKey, field)] = data;
    }

    private static getKey(metaKey: String, field: string) {
        return "_" + metaKey + "_" + field + "_";
    }


    /**
     * 获取类的父类,没有返回空数组
     * @param clas
     * @returns {any}
     */
    static getParent(clas: { new(): any ;}|Function): { new(): any ;}[] {
        let ret = Array<{ new(): any ;}>();
        let cl = Object.getPrototypeOf(clas);
        if (cl && cl instanceof Function) {
            ret.push(cl);
        }

        let meta = Meta.getData(clas, "class_parent", "") as any[];
        if (meta) {
            for (let m of meta) {
                ret.push(m);
            }
        }
        return ret;
    }

    static setParent(clas: { new(): any ;}|Function, parent: { new(): any ;}|Function) {
        let meta = Meta.getData(clas, "class_parent", "") as any[];
        if (meta == null) {
            meta = [];
            Meta.setData(clas, "class_parent", "", meta);
        }

        let par = Meta.getParent(parent);
        if (par.length > 0)
            par.forEach(it=>meta.push(it));

        meta.push(parent);

    }
}